﻿using SharpSoft.WPF;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.Windows.Input;
using System.Windows.Threading;

namespace System.Windows.Controls
{
    public static class UIElementExtensions
    {
        #region 用户操作闲置时触发
        /// <summary>
        /// 用户操作闲置时触发指定的功能
        /// </summary>
        /// <param name="element"></param>
        /// <param name="time">等待限制时长</param>
        /// <param name="action">触发的委托</param>
        public static void UserIdleRun(this FrameworkElement element, TimeSpan time, Action action)
        {
            UserIdleRunner runner = new UserIdleRunner(element, time, action);
            UserIdleRunner.SetUserIdleRunner(element, runner);
        }

        #endregion

        public static Dictionary<object, string> GetEnumSource<T>(this ItemsControl ic) where T : struct, Enum
        {
            return GetEnumSource(ic, typeof(T));
        }
        public static Dictionary<object, string> GetEnumSource(this ItemsControl ic, Type enumType)
        {
            if (!enumType.IsEnum)
            {
                throw new Exception("必须是枚举类型。");
            }
            Dictionary<object, string> dic = new Dictionary<object, string>();
            var values = Enum.GetValues(enumType);
            foreach (var value in values)
            {
                string name = Enum.GetName(enumType, value);
                if (name != null)
                {
                    // 获取枚举字段。
                    FieldInfo fieldInfo = enumType.GetField(name);
                    if (fieldInfo != null)
                    {
                        // 获取描述的属性。
                        DescriptionAttribute attr = Attribute.GetCustomAttribute(fieldInfo,
                            typeof(DescriptionAttribute), false) as DescriptionAttribute;
                        if (attr != null)
                        {
                            dic.Add(value, attr.Description);
                            continue;
                        }
                    }
                    dic.Add(value, name);
                }
            }
            return dic;
        }

        /// <summary>
        /// 设置窗体为全屏模式
        /// </summary>
        /// <param name="win"></param>
        /// <param name="noResize">是否禁止调整尺寸</param>
        /// <param name="showInTaskBar">是否在任务栏显示</param>
        /// <param name="topmost">是否置顶</param>
        public static void FullScreen(this Window win, bool noResize = false, bool showInTaskBar = true, bool topmost = false)
        {
            win.WindowStyle = WindowStyle.None;
            if (noResize)
            {
                win.ResizeMode = ResizeMode.NoResize;
            }
            win.ShowInTaskbar = showInTaskBar;
            win.Topmost = topmost;
            win.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            win.WindowState = WindowState.Maximized;

        }

        /// <summary>
        /// 获取控件所属的窗体
        /// </summary>
        /// <param name="ui"></param>
        /// <returns></returns>
        public static Window GetWindow(this UIElement ui)
        {
            if (ui is Window win)
            {
                return win;
            }

            return VisualHelper.FindParent<Window>(ui);
        }

        /// <summary>
        /// 获取并拼接基于当前运行目录的路径
        /// </summary>
        /// <param name="fe"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static string MapPath(this UIElement fe, params string[] args)
        {
            List<string> list = new List<string>();
            list.Add(AppDomain.CurrentDomain.BaseDirectory);
            list.AddRange(args);

            return System.IO.Path.Combine(list.ToArray());
        }
    }

    public class UserIdleRunner
    {
        public UserIdleRunner(FrameworkElement element, TimeSpan time, Action action)
        {
            this.Element = element;
            this.WaitTime = time;
            this.Action = action;
            element.PreviewMouseMove += Element_PreviewMouseMove;
            idleTimer = new Threading.DispatcherTimer();
            idleTimer.Interval = TimeSpan.FromSeconds(1);
            idleTimer.Tick += IdleTimer_Tick;
            IdleTime = DateTime.Now;

            element.Loaded += Element_Loaded;
            element.Unloaded += Element_Unloaded;
            if (element.IsLoaded)
            {
                idleTimer.Start();
            }
        }

        private void Element_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            IdleTime = DateTime.Now;
        }

        private void Element_Unloaded(object sender, RoutedEventArgs e)
        {
            idleTimer.Stop();
        }

        private void Element_Loaded(object sender, RoutedEventArgs e)
        {
            idleTimer.Start();
        }

        private void IdleTimer_Tick(object sender, EventArgs e)
        {
            if (DateTime.Now - IdleTime > WaitTime)
            {
                IdleTime = DateTime.Now;
                try
                {
                    Action?.Invoke();
                }
                catch (Exception)
                {

                }

            }
        }

        private static System.Windows.Threading.DispatcherTimer idleTimer;
        public DateTime IdleTime { get; private set; }

        public TimeSpan WaitTime { get; set; }

        public Action Action { get; private set; }

        public UIElement Element { get; private set; }



        public static UserIdleRunner GetUserIdleRunner(DependencyObject obj)
        {
            return (UserIdleRunner)obj.GetValue(UserIdleRunnerProperty);
        }

        public static void SetUserIdleRunner(DependencyObject obj, UserIdleRunner value)
        {
            obj.SetValue(UserIdleRunnerProperty, value);
        }

        public static readonly DependencyProperty UserIdleRunnerProperty =
            DependencyProperty.RegisterAttached("UserIdleRunner", typeof(UserIdleRunner), typeof(UserIdleRunner), new PropertyMetadata(null));

    }
}
